
#include "member_BHtmlWidget.h"
#include "member_BHtmlItem.h"
#include "member_BXmlNode.h"

using namespace BWE;

member_BHtmlWidget::member_BHtmlWidget(BHtmlWidget* htmlWidget)
{
	boss = htmlWidget;
	pagePolicy = Policy_Dynamic;
	blinkTick = 0.0;
	blinkTime = 1.0;
	readOnly = true;
	inputShown = false;
	editing = false;
	pressed = false;
	hoverItem = 0;
	inputItem = 0;
}
member_BHtmlWidget::~member_BHtmlWidget()
{

}

void member_BHtmlWidget::freshStyle(BHtmlItem* item)
{
	item_member(item)->htmlWidget = boss;

	const BString& name = item->name();
	ILineBlock& block = item_member(item)->block;

	block.setFont(fontMap(name));
	block.dirtyCells = true;

	if (name == "h1")
		item_member(item)->background.set(128, 128, 128);
	else if (name == "h2")
		item_member(item)->background.set(158, 158, 158);
	else if (name == "h3")
		item_member(item)->background.set(188, 188, 188);
	else if (name == "h4")
		item_member(item)->background.set(200, 200, 200);
	else if (name == "table")
		item_member(item)->background.set(210, 220, 215);

	item_member(item)->color.set(20, 20, 20);
	if (name == "a")
		item_member(item)->color.set(0, 60, 200);

	const BString& alignText = item->attrib("align");
	if (alignText == "left")
		item_member(item)->align = Align_Left;
	else if (alignText == "right")
		item_member(item)->align = Align_Right;
	else if (alignText == "center")
		item_member(item)->align = Align_Center;

	for (int i = 0; i < item->childCount(); i++)
	{
		BHtmlItem* child = item->child(i);
		freshStyle(child);
	}
}
void member_BHtmlWidget::freshArea()
{
	if (bodyItem)
	{
		const BRect& crect = boss->centerRect();

		if (pagePolicy != Policy_Fixed)
		{
			if (pagePolicy == Policy_Dynamic)
				pageWidth = crect.width();
			if (pagePolicy == Policy_Preferred)
				pageWidth = 0;
		}

		BSize size = item_member(bodyItem)->freshSize(pageWidth);
		item_member(bodyItem)->rect.setPos(0, 0);
		item_member(bodyItem)->adjustRect(BPoint(0, 0));

		BRect area = boss->area();
		area.setSize(size);
		boss->setArea(area);
	}
}

void member_BHtmlWidget::paintItem(BHtmlItem* item, BPainter& painter)
{
	const BString& name = item->name();
	if (name == '!')
		return;

	BPoint offset = boss->area().pos();
	BRect rect = item_member(item)->rect + offset;

	BRect crect = boss->centerRect();
	if (!crect.intersect(rect))
		return;

	item_member(item)->block.rect.setPos(rect.pos());
	if (painter.setColor(item_member(item)->background))
		painter.fillRect(rect);

	if (painter.setColor(Color_Background_Checked))
	{
		ILineBlock& block = item_member(item)->block;
		BPoint pos = block.rect.pos();
		for (int i = 0; i < block.inputCount; i++)
		{
			CodeCell& cell = block.cells[block.inputIndex + i];
			painter.fillRect(cell.rect + pos);
		}
	}

	if (painter.setColor(item_member(item)->color))
		item_member(item)->block.paint(painter);

	BArray<BXmlNodeHolder>& children = xml_member(item)->children;
	for (int i = 0; i < children.size(); i++)
	{
		BHtmlItem* child = (BHtmlItem*)children[i].ptr();
		paintItem(child, painter);
	}
}

bool member_BHtmlWidget::seekPrevWord()
{
	if (item_member(inputItem)->block.seekPrevWord() < 0)
		item_member(inputItem)->block.inputIndex = 0;
	inputShown = true;
	blinkTick = clock() + 500;
	boss->fresh();
	return true;
}
bool member_BHtmlWidget::seekNextWord()
{
	item_member(inputItem)->block.seekNextWord();
	inputShown = true;
	blinkTick = clock() + 500;
	boss->fresh();
	return true;
}
bool member_BHtmlWidget::seekPrev()
{
	if (inputItem)
	{
		if(item_member(inputItem)->block.seekPrevCode() < 0)
			item_member(inputItem)->block.inputIndex = 0;
		inputShown = true;
		blinkTick = clock() + 500;
		boss->fresh();
		return true;
	}
	return false;
}
bool member_BHtmlWidget::seekNext()
{
	if (inputItem)
	{
		item_member(inputItem)->block.seekNextCode();
		inputShown = true;
		blinkTick = clock() + 500;
		boss->fresh();
		return true;
	}
	return false;
}

bool member_BHtmlWidget::removeSelection()
{
	if (!inputItem)
		return false;
	if (item_member(inputItem)->block.removeSelection())
	{
		editing = true;
		dirty = true;
		return true;
	}
	return false;
}
bool member_BHtmlWidget::removeIndex()
{
	int index = item_member(inputItem)->block.inputIndex;
	if (item_member(inputItem)->block.remove(index))
	{
		editing = true;
		dirty = true;
		return true;
	}
	return false;
}

void member_BHtmlWidget::itemTextEdited(BHtmlItem* item)
{
	dirty = true;
	editing = true;
	xml_member(item)->text = (item_member(item)->block.text);
	ConvertTextToHtml(xml_member(item)->text);
	boss->emit(Signal_ItemChanged, item);
	boss->emit(Signal_ItemEdited, item);
	boss->fresh();
}

BHtmlItem* member_BHtmlWidget::itemAt(const BPoint& pos, BHtmlItem* item)
{
	if (item == 0)
		return 0;
	BPoint offset = boss->area().pos();
	BRect rect = item_member(item)->rect + offset;;
	if (rect.contain(pos))
	{
		for (int i = 0; i < item->childCount(); i++)
		{
			BHtmlItem* child = item->child(i);
			BHtmlItem* ret = itemAt(pos, child);
			if (ret)
				return ret;
		}
		return item;
	}
	return 0;
}
BHtmlItem* member_BHtmlWidget::itemOfId(BHtmlItem* item, const BString& id)
{
	if (item->attrib("id") == id)
		return item;
	for (int i = 0; i < item->childCount(); i++)
	{
		BHtmlItem* child = item->child(i);
		BHtmlItem* ret = itemOfId(child, id);
		if (ret)
			return ret;
	}
	return 0;
}
